use std::{fs::File, io::Read};

use actix_cors::Cors;
use actix_web::{App, HttpServer};
use log::info;
use openssl::{
    pkey::PKey,
    ssl::{SslAcceptor, SslAcceptorBuilder, SslMethod},
};
use rbase::log_init;

use anyhow::Result;
use anyhow::anyhow;
use rbase_iam::rest_api::service::auth_check;

pub mod db;
pub mod rest_api;
pub mod service;

static SERVER_PORT: u16 = 7443;
static USE_SSL: bool = true;

#[actix_web::main]
async fn main() -> Result<()> {
    log_init::init()?;

    rbase::db::init()?;
    rbase_iam::db::init().await?;
    db::init().await?;

    info!("Server started");

    let mut httpserver = HttpServer::new(|| {
        // 配置 CORS
        let cors = Cors::default()
            // 允许来自前端的源（根据实际情况修改）
            .allow_any_origin()
            .supports_credentials()
            // 允许的 HTTP 方法
            .allowed_methods(vec!["GET", "POST", "PUT", "DELETE", "OPTIONS"])
            // 允许的请求头
            .allowed_headers(vec![
                actix_web::http::header::AUTHORIZATION,
                actix_web::http::header::ACCEPT,
                actix_web::http::header::CONTENT_TYPE,
            ])
            // 预检请求的缓存时间（秒），减少预检请求次数
            .max_age(3600);

        App::new()
            .wrap(cors)
            .wrap(auth_check::CheckLogin)
            // iam
            .configure(rbase_iam::rest_api::config)
            // 配置静态文件服务 放在最后, 以免路径冲突
            .configure(rest_api::config)
    });
    httpserver = if USE_SSL {
        httpserver.bind_openssl(("127.0.0.1", SERVER_PORT), gen_ssl_acceptor_builder()?)?
    } else {
        httpserver.bind(("127.0.0.1", SERVER_PORT))?
    };
    httpserver.run().await.or_else(|err| Err(anyhow!("Error running server: {}", err)))
}

fn gen_ssl_acceptor_builder() -> Result<SslAcceptorBuilder> {
    let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).or_else(|e| Err(anyhow!("Failed to create SSL acceptor: {}", e)))?;

    // 加载私钥
    let key_file_path = "config/key.pem";
    let mut key_file = File::open(key_file_path).or_else(|e| Err(anyhow!("Failed to open key file {key_file_path}: {}", e)))?;
    let mut key_buf = Vec::new();
    key_file
        .read_to_end(&mut key_buf)
        .or_else(|e| Err(anyhow!("Failed to read key file {key_file_path}: {}", e)))?;

    let key = PKey::private_key_from_pem_passphrase(&key_buf, "11111".as_bytes()).or_else(|e| Err(anyhow!("Failed to create private key: {}", e)))?;
    builder.set_private_key(&key).or_else(|e| Err(anyhow!("Failed to set private key: {}", e)))?;

    let cert_file_path = "config/cert.pem";
    builder
        .set_certificate_chain_file(cert_file_path)
        .or_else(|e| Err(anyhow!("Failed to set certificate chain file {cert_file_path}: {}", e)))?;
    Ok(builder)
}
